﻿Imports System.IO
Imports System.Net
Imports System.Text
Imports System.Runtime.CompilerServices

Public Module Extensions
    <Extension()>
    Public Async Function WriteAsync(response As HttpListenerResponse, content As String) As Task
        ' 将字符串转换为字节数组
        Dim buffer As Byte() = Encoding.UTF8.GetBytes(content)
        ' 设置响应的内容类型和编码
        response.ContentEncoding = Encoding.UTF8
        response.ContentType = WebAPI.ContentType.TextPlain   ' 使用传入的 contentType 或默认值
        response.ContentLength64 = buffer.Length
        ' 异步写入输出流
        Await response.OutputStream.WriteAsync(buffer, 0, buffer.Length)
        ' 关闭输出流
        response.OutputStream.Close()
    End Function

    <Extension()>
    Public Function GetString(request As HttpListenerRequest) As String
        Using reader As New StreamReader(request.InputStream, Encoding.UTF8)
            Return reader.ReadToEnd()
        End Using
    End Function

    <Extension()>
    Public Function GetToken(request As HttpListenerRequest) As String
        Dim token As String = ""
        If request.Headers("Authorization") IsNot Nothing Then
            Dim authHeader As String = request.Headers("Authorization")
            token = authHeader
        End If
        Return token
    End Function
    ''' <summary>
    ''' 发送文件，扩展名自动识别（zip/json/xml/txt/html/jpg/jpeg/png/gif/bmp），否则以二进制文件标识返回（application/octet-stream）
    ''' </summary>
    ''' <param name="response">响应体</param>
    ''' <param name="filePath">文件完整路径</param>
    ''' <returns></returns>
    <Extension()>
    Public Async Function SendFileAsync(response As HttpListenerResponse, filePath As String) As Task
        ' 检查文件是否存在
        If File.Exists(filePath) Then
            ' 获取文件扩展名
            Dim fileExtension As String = Path.GetExtension(filePath).ToLowerInvariant()
            Dim contentType As String

            ' 根据文件扩展名设置Content-Type
            Select Case fileExtension.ToLower()
                Case ".zip"
                    contentType = "application/zip"
                Case ".json"
                    contentType = "application/json;charset=UTF-8"
                Case ".css"
                    contentType = "text/css;charset=UTF-8"
                Case ".js"
                    contentType = "application/javascript;charset=UTF-8"
                Case ".xml"
                    contentType = "application/xml;charset=UTF-8"
                Case ".txt"
                    contentType = "text/plain;charset=UTF-8"
                Case ".html"
                    contentType = "text/html;charset=UTF-8"
                Case ".jpg", ".jpeg"
                    contentType = "image/jpeg"
                Case ".png"
                    contentType = "image/png"
                Case ".gif"
                    contentType = "image/gif"
                Case ".bmp"
                    contentType = "image/bmp"
                ' 其他常见文件类型
                Case ".pdf"
                    contentType = "application/pdf"
                Case ".csv"
                    contentType = "text/csv;charset=UTF-8"
                Case ".svg"
                    contentType = "image/svg+xml;charset=UTF-8"
                Case Else
                    contentType = "application/octet-stream" ' 默认二进制文件
            End Select


            response.ContentType = contentType

            ' 写入响应头，例如Content-Disposition用于建议浏览器以附件形式下载文件
            response.AddHeader("Content-Disposition", "attachment; filename=""" & Path.GetFileName(filePath) & """")

            ' 设置响应头，例如Content-Length用于指示文件大小
            Dim fileSize As Long = New FileInfo(filePath).Length
            response.ContentLength64 = fileSize

            ' 异步发送文件内容
            Using fileStream As FileStream = File.OpenRead(filePath)
                Await fileStream.CopyToAsync(response.OutputStream)
            End Using

            ' 关闭响应流（这将自动发送HTTP响应）
            response.Close()
        Else
            ' 如果文件不存在，发送错误响应
            response.StatusCode = CType(HttpStatusCode.NotFound, Integer)
            response.StatusDescription = "File Not Found"
            response.Close()
        End If
    End Function
End Module
